using Godot;
using System;

namespace CurrentGame.Placements;


public partial class LightPlayerDetect : Node2D
{

    [Export]
    public int PixelLength { get; set; } = 128;
    [Export]
    public int SizeOffset { get; set; } = 14;
    [Export]
    public uint CollisionMask { get; set; } = 536870914;
    [Export]
    public bool Monitoring { get; set; } = true;

    // Node reference
    private Node2D _lightRoot;
    private Player _player;

    private Vector2 _savedScale, _rayCastLeft, _rayCastRight, _sourceLeft, _sourceRight, _middleCast;
    private PhysicsRayQueryParameters2D _leftQuery, _rightQuery, _middleQuery;
    private bool _playerDetected = false, _initialized = false;
    private Rid _targetRid;

    public override void _Ready()
    {
        var map = GetNode<NodeReferenceMap>(Constants.NodeRefMapPath);
        _player = map.MainPlayer;
        _lightRoot = GetNode<Node2D>("..");
        _savedScale = _lightRoot.Scale;

        var delta = new Vector2(0.0f, (float)PixelLength * _savedScale.Y);
        _sourceLeft = new Vector2(GlobalPosition.X - (float)SizeOffset * _savedScale.X, GlobalPosition.Y);
        _rayCastLeft = _sourceLeft + delta;
        _sourceRight = new Vector2(GlobalPosition.X + (float)SizeOffset * _savedScale.X, GlobalPosition.Y);
        _rayCastRight = _sourceRight + delta;
        _middleCast = GlobalPosition + delta;

        _leftQuery = new PhysicsRayQueryParameters2D()
        {
            CollideWithAreas = true,
            CollisionMask = CollisionMask,
            From = _sourceLeft,
            To = _rayCastLeft,
        };
        _rightQuery = new PhysicsRayQueryParameters2D()
        {
            CollideWithAreas = true,
            CollisionMask = CollisionMask,
            From = _sourceRight,
            To = _rayCastRight,
        };
        _middleQuery = new PhysicsRayQueryParameters2D()
        {
            CollideWithAreas = true,
            CollisionMask = CollisionMask,
            From = GlobalPosition,
            To = _middleCast,
        };
    }

    public override void _PhysicsProcess(double delta)
    {
        if (!Monitoring) return;

        if (!_initialized)
        {
            _targetRid = _player.GetAreaDetectorRID();
            _initialized = true;
        }

		var spaceState = GetWorld2D().DirectSpaceState;
        var leftResult = spaceState.IntersectRay(_leftQuery);
        var rightResult = spaceState.IntersectRay(_rightQuery);
        var middleResult = spaceState.IntersectRay(_middleQuery);

        var found = false;
        if (leftResult.Count > 0)
        {
            //GD.Print(leftResult["collider"]);
            if (leftResult["rid"].AsRid() == _targetRid) found = true;
        }
        if (rightResult.Count > 0)
        {
            //GD.Print(rightResult["collider"]);
            if (rightResult["rid"].AsRid() == _targetRid) found = true;
        }
        if (middleResult.Count > 0)
        {
            //GD.Print(middleResult["collider"]);
            if (middleResult["rid"].AsRid() == _targetRid) found = true;
        }
        if (!_playerDetected && found)
        {
            _playerDetected = true;
            _player.EnterLightArea(this);
        }
        else if (_playerDetected && !found)
        {
            _playerDetected = false;
            _player.LeaveLightArea(this);
        }
    }
}
